using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.EntityClient;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Common;
using System.Data.SqlClient;


namespace xiushen.Domain
{
    //public interface IRepository { }

    //public interface IReadOnlyRepository<TEntity, TId> : IRepository
    //{
    //    /// <summary>
    //    /// Returns each entity of a certain type.
    //    /// </summary>
    //    /// <returns></returns>
    //    IEnumerable<TEntity> GetAll();

    //    /// <summary>
    //    /// Returns each entity of a certain type according to the given expression.
    //    /// </summary>
    //    /// <param name="expression"></param>
    //    /// <returns></returns>
    //    IEnumerable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression);

    //    /// <summary>
    //    /// Returns a query which does a select all.
    //    /// </summary>
    //    /// <returns></returns>
    //    IQueryable<TEntity> QueryAll();

    //    /// <summary>
    //    /// Returns the entity for the given identifier, or null if no entity exists.
    //    /// </summary>
    //    /// <param name="id"></param>
    //    /// <returns></returns>
    //    TEntity Get(TId id);

    //    /// <summary>
    //    /// Counts each entity of a certain type.
    //    /// </summary>
    //    /// <returns></returns>
    //    int CountAll();

    //    /// <summary>
    //    /// Counts each entity of a certain type according to the given expression.
    //    /// </summary>
    //    /// <param name="expression"></param>
    //    /// <returns></returns>
    //    int Count(Expression<Func<TEntity, bool>> expression);

    //    /// <summary>
    //    /// Checks if an entity with the given identifier exists.
    //    /// Returns true if the entity exists, else false.
    //    /// </summary>
    //    /// <param name="id"></param>
    //    /// <returns></returns>
    //    bool Exists(TId id);

    //    /// <summary>
    //    /// Checks if the query returns a result.
    //    /// </summary>
    //    /// <param name="queryable"></param>
    //    /// <returns></returns>
    //    bool Exists(IQueryable<TEntity> queryable);

    //    /// <summary>
    //    /// Checks if an entity exists according to the given expression.
    //    /// </summary>
    //    /// <param name="expression"></param>
    //    /// <returns></returns>
    //    bool Exists(Expression<Func<TEntity, bool>> expression);
    //}

    public abstract class ReadOnlyRepository<TEntity>  :IRepository
        //: IReadOnlyRepository<TEntity, TId>
        where TEntity : EntityObject
    {

        private Entities _entities;

        protected ReadOnlyRepository()
        {
            _entities = new Entities();
        }

        protected IObjectContext ObjectContext
        {
            get
            {
                return _entities;
            }
        }

        public IQueryable<TEntity> QueryAll()
        {
            return ObjectContext.CreateQuery<TEntity>();
        }

        public IQueryable<T> QueryAll<T>()
        {
            return ObjectContext.CreateQuery<T>();
        }

       

        public IEnumerable<TElement> ExecuteStoreQuery<TElement>(string commandText, params object[] parameters)
        {

            return ObjectContext.ExecuteStoreQuery<TElement>(commandText, parameters);
        }

        public IQueryable<TEntity> QueryAll(Expression<Func<TEntity, bool>> expression)
        {
            return QueryAll().Where(expression);
        }
        public IQueryable<T> QueryAll<T>(Expression<Func<T, bool>> expression)
        {
            return QueryAll<T>().Where(expression);
        }
        public IEnumerable<TEntity> GetAll()
        {
            return QueryAll().ToList();
        }

        public TEntity Get(object id)
           
        {
            if (id == null)
            {
                return null;
            }

            var entityKey = ObjectContext.CreateEntityKey<TEntity, object>(id);

            try
            {
                return (TEntity)ObjectContext.GetObjectByKey(entityKey);
            }
            catch (ObjectNotFoundException)
            {
                return null;
            }
        }
        public IEnumerable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression)
        {
            return QueryAll().Where(expression).ToList();
        }

     
        public int CountAll()
        {
            return QueryAll().Count();
        }

        public int Count(Expression<Func<TEntity, bool>> expression)
        {
            return QueryAll().Where(expression).Count();
        }

       

        public bool Exists(IQueryable<TEntity> queryable)
        {
            return queryable.Count() > 0;
        }

        public bool Exists(Expression<Func<TEntity, bool>> expression)
        {
            return Exists(QueryAll().Where(expression));
        }

      
    }
}